/***2024-12-15 迷途小羔羊
* 用于编写处理外部拽文件的工具类
*/
namespace GYLite
{
    export class FilesDropUtil
    {
        private static _dropList:IDropFileObject[]=[];
        /**添加拖拽文件接收监听对象，最后监听的对象优先接收，同时只能有一个对象接收
         * @param obj 拖拽接收对象
        */
        public static addDropObj(obj:IDropFileObject):void
        {
            let ind:number = FilesDropUtil.findDropIndex(obj);
            if(ind > -1)
                FilesDropUtil._dropList.splice(ind, 1);
            FilesDropUtil._dropList[FilesDropUtil._dropList.length] = obj;
        }
        /**移除拖拽文件接收监听对象，最后监听的对象优先接收，同时只能有一个对象接收
         * @param obj 拖拽接收对象
        */
        public static removeDropObj(obj:IDropFileObject):void
        {
            let ind:number = FilesDropUtil.findDropIndex(obj);
            if(ind > -1)
                FilesDropUtil._dropList.splice(ind, 1);            
        }
        /**开启拖拽监听*/
        public static openRecFile():void
		{
			if(GYLite.GYSprite.player && GYLite.GYSprite.player.canvas && GYLite.GYSprite.player.canvas.ondrop == null)
			{
				GYLite.GYSprite.player.canvas.ondrop = FilesDropUtil.dropFiles;
				GYLite.GYSprite.player.canvas.ondragover = FilesDropUtil.defaultOnDragOver;
				GYLite.GYSprite.player.canvas.ondragenter = FilesDropUtil.defaultOnDragEnter;
			}
		}
        private static findDropIndex(obj:IDropFileObject):number
        {
            let len:number;
            let dropObj:IDropFileObject;
            let arr:IDropFileObject[];
            arr = FilesDropUtil._dropList;
            len = arr.length;
            while(--len>-1)
            {
                dropObj = arr[len];
                if(dropObj.thisObj.disposed)
                {
                    arr.splice(len, 1);
                    continue;
                }
                if(dropObj.dropCallBack == obj.dropCallBack && dropObj.thisObj == obj.thisObj)
                    return len;
            }
            return -1;
        }
        
        /**关闭拖拽监听*/
        public static closeRecFile():void
		{
			if(GYLite.GYSprite.player && GYLite.GYSprite.player.canvas)
			{
				GYLite.GYSprite.player.canvas.ondrop = null;
				GYLite.GYSprite.player.canvas.ondragover = null;
				GYLite.GYSprite.player.canvas.ondragenter = null;
			}
		}
        protected static dropFiles(e:DragEvent):void
		{			
			e.preventDefault();
            if(FilesDropUtil._dropList.length == 0)
                return;
			FilesDropUtil.dragCall(e, FilesDropUtil._dropList[FilesDropUtil._dropList.length - 1]);
        }
        private static defaultOnDragOver(e:DragEvent):void
        {
            e.preventDefault();
            if(FilesDropUtil._dropList.length == 0)
                return;
			FilesDropUtil.dragCall(e, FilesDropUtil._dropList[FilesDropUtil._dropList.length - 1]);
        }
        private static defaultOnDragEnter(e:DragEvent):void
        {
            e.preventDefault();
            if(FilesDropUtil._dropList.length == 0)
                return;
			FilesDropUtil.dragCall(e, FilesDropUtil._dropList[FilesDropUtil._dropList.length - 1]);
        }
        private static dragCall(e:DragEvent,dropObj:IDropFileObject):void
        {
            if(dropObj == null || dropObj.dropCallBack == null)
                return;
            if((dropObj.flag & DropFlag.ENTER) != 1 && e.type == 'dragenter')
                return;
            if((dropObj.flag & DropFlag.OVER) != 1 && e.type == 'dragover')
                return;
            if((dropObj.flag & DropFlag.DROP) != 1 && e.type == 'drop')
                return;
            var arr:DataTransferItemList;            
            let item:DataTransferItem;
            let entry:FileSystemEntry;
            let result:FileSystemFileEntry[];
            let count:number;            
            let i:number,len:number;
            result = [];
            arr = e.dataTransfer.items;
            count = len = arr.length;
            for(i=0;i<len;++i)
            {
                item = <any>arr[i];
                if(item.kind == "file")
                {
                    entry = item.webkitGetAsEntry();
                    FilesDropUtil.readDir(entry, result, function(result:FileSystemFileEntry[]):void{
                        --count;
                        if(count == 0)
                        {
                            //延迟100毫秒，以便页面获得焦点
                            GYLite.TimeManager.timeOut(dropObj.dropCallBack, dropObj.thisObj, 100, e, result);                            
                        }
                    }, this);
                }
            }  
        }
        protected static readDir(entry:FileSystemEntry, result:FileSystemFileEntry[], callBack:Function, thisObj:any,param:any=null):void
        {
            if(result == null)
                result = [];
            if(param == null)
                param = {count:1}            
            if(entry.isDirectory)
            {
                var directoryReader:FileSystemDirectoryReader;
                directoryReader = (<FileSystemDirectoryEntry>entry).createReader();                
                directoryReader.readEntries(function(entries:FileSystemEntry[]) {                    
                    --param.count;
                    param.count += entries.length;
                    entries.forEach(function(entry:FileSystemEntry) {
                        FilesDropUtil.readDir(entry, result, callBack, thisObj, param);
                    });                    
                },function(err: DOMException):void{
                    console.error(err.stack);                    
                    --param.count;
                    if(param.count == 0 && callBack!=null)
                        callBack.call(thisObj, result);
                });    
            }
            else
            {                
                --param.count;
                result[result.length] = <FileSystemFileEntry>entry;                
                if(param.count == 0 && callBack!=null)
                    callBack.call(thisObj, result);
            }            
        }
        public static disposed:boolean;
        public static dispose():void
        {
            if(this.disposed)return;
            this.disposed = true;
            this._dropList.length = 0;
            this.closeRecFile();
        }
    }
    export interface IDropFileObject{
        /**回调,延迟将会100毫秒，以便页面获得焦点*/dropCallBack:(e:DragEvent,result:FileSystemFileEntry[])=>void;        
        thisObj:GYLite.IResource;
        /**监听模式，参考DropFlag常量，1 放置 2拖入 4经过，监听多个标志值相加*/flag:number;
    }
    export enum DropFlag
    {
        DROP = 1,
        ENTER = 2,
        OVER = 4,
    }
}